package com.chinawayltd.ews.sample.taskCenter;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.TriggerBuilder.newTrigger;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.MapUtils;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.chinawayltd.ews.sample.mapper.TaskProducerMapper;
import com.chinawayltd.ews.sample.util.spring.SpringContextUtil;

@SuppressWarnings({ "unchecked" })
public class TaskProducerJob implements Job {
	
	private static Logger logger = LoggerFactory.getLogger(TaskProducerJob.class);
	
	private static final String GROUP_NAME = "TASK_PRODUCER_JOB";
	private static final int JOB_TYPE_STATEFUL = 2;

	private TaskProducerMapper taskProducerMapper;
	
	public TaskProducerMapper getTaskProducerMapper() {
		if (this.taskProducerMapper == null) {
			taskProducerMapper = SpringContextUtil.getBean(TaskProducerMapper.class);
		}
		return taskProducerMapper;
	}

	public void execute(JobExecutionContext context) throws JobExecutionException {
		Scheduler scheduler = context.getScheduler();
		//查询数据获取所有任务信息
		List<Map<String, Object>> taskDefList = this.getTaskProducerMapper().findTaskDef();
		cleanTask(scheduler, taskDefList);
		updateTask(scheduler, taskDefList);
	}

	/**
	 * 检查定时任务工厂运行的任务是否有在数据库中有改变状态
	 * @param scheduler
	 * @param taskDefList
	 */
	private void updateTask(Scheduler scheduler, List<Map<String, Object>> taskDefList) {
		//检查定时任务工厂运行的任务是否有在数据库中有改变状态
		for (Map<String, Object> map : taskDefList) {
			String taskName = MapUtils.getString(map, "TASK_NAME");
			try {
				String taskJobName = MapUtils.getString(map, "JOB_NAME");
				Integer jobType = MapUtils.getInteger(map, "JOB_TYPE");
				String taskId = MapUtils.getString(map, "ID");
				String taskStatus = MapUtils.getString(map, "TASK_STATUS");
				String cron = MapUtils.getString(map, "CRON_EXPRESSION");
				JobKey jobKey = new JobKey(taskId, GROUP_NAME);
				TriggerKey triggerKey = new TriggerKey(taskName, GROUP_NAME);
				if ("1".equalsIgnoreCase(taskStatus)) {
					JobDetail job = JobBuilder.newJob((jobType != null && jobType == JOB_TYPE_STATEFUL) ? TaskStatefulCreateJob.class : TaskCreateJob.class)
							.withIdentity(jobKey).usingJobData(TaskConsts.TASK_JOB_NAME, taskJobName)
                            .usingJobData(TaskConsts.TASK_HAS_LOG, MapUtils.getInteger(map, "HAS_LOG"))
							.usingJobData(TaskConsts.HAVE_LOCK, MapUtils.getInteger(map, "HAVE_LOCK"))
                            .usingJobData(TaskConsts.LOCK_EXPIRE_TIME, MapUtils.getInteger(map, "LOCK_EXPIRE_TIME"))
                            .build();
					CronTriggerImpl trigger = (CronTriggerImpl) newTrigger().withIdentity(triggerKey)
							.withDescription(taskName).startAt(new Date()).withSchedule(cronSchedule(cron)).forJob(job)
							.build();
					JobDetail dupeJ = scheduler.getJobDetail(jobKey);
					if (dupeJ != null) {
						CronTriggerImpl triggerJ = (CronTriggerImpl) scheduler.getTrigger(triggerKey);
						// 表达式不同
						if (!triggerJ.getCronExpression().equalsIgnoreCase(cron)) {
							scheduler.rescheduleJob(triggerKey, trigger);
							logger.info("=========任务：【" + taskName + "】corn表达式已被更改，并在定时器管理器中更新！" );
						}
					} else {
						scheduler.scheduleJob(job, trigger);
						logger.info("=========启动任务：【" + taskName + "】！" );
					}
				} else if ("0".equalsIgnoreCase(taskStatus)) {
					JobDetail dupeJ = scheduler.getJobDetail(jobKey);
					if (dupeJ != null) {
						scheduler.deleteJob(jobKey);
						logger.info("=========任务：【" + taskName + "】已被禁用，并在定时器管理器中清除！" );
					}
				}
			} catch (Exception e) {
				logger.error("JOB运行错误：" + taskName, e);
			}
		}
	}

	/**
	 * 检查目前定时任务工厂运行的定时任务是否跟数据库任务数据一致,如果不一致则直接删除定时任务
	 * @param scheduler
	 * @param taskDefList
	 */
	private void cleanTask(Scheduler scheduler, List<Map<String, Object>> taskDefList) {
		try {
			List<String> groups = scheduler.getJobGroupNames();
			for (String group : groups) {
				if (group.endsWith(GROUP_NAME)) {
					GroupMatcher<JobKey> g = GroupMatcher.groupEquals(GROUP_NAME);
					Set<JobKey> jobs = scheduler.getJobKeys(g);
					for (JobKey key : jobs) {
						String jobKeyName = key.getName();
						boolean inResult = false;
						for (Map<String, Object> map : taskDefList) {
							String jobName = MapUtils.getString(map, "ID");
							if (jobKeyName.equals(jobName)) {
								inResult = true;
								break;
							}
						}
						if (!inResult) {
							scheduler.deleteJob(key);
							logger.info("=========发现数据库中已没有任务：【" + jobKeyName + "】并在定时器管理器中清除！" );
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("JOB定时维护失败：", e);
		}
	}

}
